﻿using System;
using System.Collections.Generic;
using System.Net.Http.Headers;
using System.Text;
using Hangfire.Annotations;
using Microsoft.AspNetCore.Http;
using System.Linq;

namespace Hangfire.Dashboard.Authorization
{
    public class BasicAuthAuthorizationFilter : IDashboardAuthorizationFilter
    {
        private readonly BasicAuthAuthorizationFilterOptions _options;
        public BasicAuthAuthorizationFilter()
            : this(new BasicAuthAuthorizationFilterOptions())
        {
        }
        public BasicAuthAuthorizationFilter(BasicAuthAuthorizationFilterOptions options)
        {
            _options = options;
        }
        public bool Authorize([NotNull] DashboardContext context)
        {
            if (_options.Users == null || _options.Users.Count() == 0)
                return true;

            var httpContext = context.GetHttpContext();
            string header = httpContext.Request.Headers["Authorization"];
            if (String.IsNullOrWhiteSpace(header) == false)
            {
                AuthenticationHeaderValue authValues = AuthenticationHeaderValue.Parse(header);
                if ("Basic".Equals(authValues.Scheme, StringComparison.InvariantCultureIgnoreCase))
                {
                    string parameter = Encoding.UTF8.GetString(Convert.FromBase64String(authValues.Parameter));
                    var parts = parameter.Split(':');

                    if (parts.Length > 1)
                    {
                        string login = parts[0];
                        string password = parts[1];
                        return _options.Users.Any(it => it.UserName == login && it.Password == password) || Challenge(httpContext);
                    }
                }
            }
            return Challenge(httpContext);
        }

        private bool Challenge(HttpContext context)
        {
            context.Response.StatusCode = 401;
            context.Response.Headers.Append("WWW-Authenticate", "Basic realm=\"Hangfire Dashboard\"");
            //context.Response.WriteAsync("Authentication is required.").Wait();
            return false;
        }
    }
}
